home *** CD-ROM | disk | FTP | other *** search
/ MacFormat España 15 / macformat_15.iso / C de cerca / Ejemplos / Capítulo 5 / CdeCerca.c < prev   
C/C++ Source or Header  |  1996-01-24  |  25KB  |  705 lines

  1. /*****************************************************************/
  2. /*
  3.         C de Cerca 5
  4.         Menú Edición, Texto, cuerpo de texto y color.
  5.         Rafael Escoté - Enric Herrera
  6.         BlauSoft S.L. para MacFormat España - 1996
  7.                     
  8.         La descripción del código y la información sobre cómo preparar
  9.         el entorno de programación y generar estos programas, está contenida
  10.         en el ejemplar de MacFormat que los acompaña.
  11.  
  12. */
  13. /*****************************************************************/
  14.  
  15. /*
  16. LA TOOLBOX Y LOS FICHEROS 'UNIVERSAL HEADERS'
  17. ==============================================
  18. La Toolbox es una colección de funciones escritas por Apple
  19. que han sido ya compiladas y colocadas en los chips de ROM de cada
  20. Mac. 
  21. Para poder emplear en nuestros programas una de dichas funciones,
  22. debemos informar al compilador acerca de los posibles parámetros
  23. y valores de salida requeridos.
  24. En otras palabras, el compilador necesita el prototipo de la función
  25. existente en la Toolbox de forma que pueda verificar que el uso que de
  26. ella hagamos en nuestro programa sea correcto.
  27. Los ficheros APPLE UNIVERSAL HEADERS proporcionados por Apple no
  28. son más que ficheros de texto conteniendo los prototipos de cada una de
  29. las funciones de la Toolbox.
  30.  
  31. NOTA: Sólo para los más curiosos: En la carpeta que contiene el compilador,
  32. veréis una carpeta llamada 'MacOS Support' y en su interior una carpeta
  33. llamada 'Headers' y dentro de ella una carpeta llamada
  34. 'Universal Headers', que contiene todos los ficheros creados por Apple.
  35. */
  36.  
  37.  
  38. /* 
  39. COMO DIFERENCIAR FUNCIONES PROPIAS Y DE LA TOOLBOX
  40. ===================================================
  41. A las funciones creadas por nosotros para este programa (y que por lo
  42. tanto no pertenecen a la Toolbox) les hemos dado nombres que comienzan
  43. por las iniciales MF. Por ejemplo, MF_PlaySnd(), MF_RandomColor() etc...
  44. Todas las restantes funciones que aparecen empleadas en el código, SON
  45. FUNCIONES PERTENECIENTES A LA TOOLBOX DE APPLE.
  46. (Una excepción: La función main() la hemos creado nosotros pero su nombre
  47. no puede ser otro que main(), por convención)
  48.  
  49.  
  50.  
  51. /****************************************************************    */
  52. /* PROTOTIPOS    DE LAS FUNCIONES QUE HEMOS CREADO                                         */
  53. /* PARA NUESTRO PROGRAMA                                                                                    */ 
  54. /****************************************************************    */
  55. void        main(void);                /* Esta función NO puede tener otro nombre */
  56. void         MF_RandomColor        (void);
  57. short     MF_ValorAlAzar        (short min, short max);
  58. void        MF_InitToolbox         (void);
  59. void         MF_SetupMenus            (void);
  60. void         MF_AbreMiVentana    (void);
  61. void         MF_bucle_principal(void);
  62. void         MF_MenuBar                (long algoSeleccionado);
  63. void         MF_EscribeTexto        (void);
  64. void         MF_Update                    (WindowPtr ventana_a_refrescar);
  65.  
  66.  
  67.  
  68. /****************************************************************    */
  69. /* CONSTANTES Y VARIABLES GLOBALES                                                                 */
  70. /* DE USO GENERAL                                                                                                    */ 
  71. /****************************************************************    */
  72. Boolean gAcabarProg = false; /* Una variable global. 
  73.                                                                 Como siempre, las variables globales
  74.                                                                 las prefijamos con la letra 'g'.
  75.                                                                 Cuando gAcabarProg sea = true,
  76.                                                                 acabaremos el programa */
  77.  
  78.                                                 
  79.  
  80. /****************************************************************    */
  81. /* CONSTANTES DEFINIENDO EL NUMERO DE RECURSO    (resource)                    */
  82. /* CORRESPONDIENTE A LA VENTANA DE ALERTA QUE ABRIREMOS                        */
  83. /* CUANDO EL USUARIO SELECCIONE 'Acerca de C de Cerca...'                    */
  84. /* DEL MENU Apple 
  85. /****************************************************************    */
  86. #define kAlertRsrcID    128    /* ALRT */
  87.  
  88.  
  89.  
  90. /****************************************************************    */
  91. /* CONSTANTES Y VARIABLES GLOBALES                                                                 */
  92. /* RELACIONADAS CON LOS MENUS EN NUESTRO PROGRAMA                                    */ 
  93. /****************************************************************    */
  94. #define            kAppleMenuID        128
  95. #define            kArchivoMenuID    129
  96. #define            kEdicionMenuID    130 /* MENU */
  97. #define            kAcercaDe_Item    1
  98. #define            kDemoTexto            1
  99. #define            kSalirItem            3
  100.  
  101. MenuRef            gAppleMenu;
  102. MenuRef            gArchivoMenu;
  103. MenuRef            gEdicionMenu;
  104.  
  105.  
  106.  
  107. /****************************************************************    */
  108. /* CONSTANTES Y VARIABLES GLOBALES                                                                 */
  109. /* RELACIONADAS CON LA VENTANA QUE ABRIREMOS                                            */ 
  110. /****************************************************************    */
  111.  
  112. /* Una constante con el numero de recurso de la ventana que hemos creado
  113.      empleando ResEdit */
  114. #define         kMiVentanaRsrcID    128
  115.  
  116. WindowPtr        gMiVentana = nil; /*  Variable de tipo 'pointer'.
  117.                                                                 Puntero a una estructura
  118.                                                                 de tipo WindowRecord  definida por Apple
  119.                                                                 en el fichero UNIVERSAL HEADER Windows.h
  120.                                                                 y que corresponderá 
  121.                                                                 a la ventana que crearemos 
  122.                                                                 NOTA sólo para curiosos: De hecho,
  123.                                                                 una variable WindowPtr apunta a la 
  124.                                                                 estructura GrafPort que forma parte de
  125.                                                                 la estructura WindowRecord. */
  126.  
  127.  
  128.  
  129. /*--------------------------------------------------------------------*/
  130. /* A PARTIR DE ESTE PUNTO, APARECE EL CODIGO DE LAS FUNCIONES CREADAS
  131.     ESPECIFICAMENTE PARA ESTE PROGRAMA. */
  132. /*--------------------------------------------------------------------*/
  133.  
  134.  
  135.  
  136. /****************************************************************    */
  137. /* main()                                                                 */
  138. /****************************************************************    */
  139. /*
  140.     Todos los programas en C poseen una función que debe llamarse main.
  141.     (NO PERTENECE A LA TOOLBOX)
  142.     Cuando un programa se pone en marcha, lo hace SIEMPRE ejecutando
  143.     en primer lugar la función main().
  144.     Es el punto de entrada a nuestra aplicación.
  145.     
  146.     Recibe:     nada
  147.     Que hace: Crea menús y pone una ventana en pantalla etc...
  148.     Salida:      void (nada)
  149. */
  150. void    main (void)
  151. {    
  152.     /* Antes de hacer nada, debemos inicializar la Toolbox del Mac                 */
  153.     /* Como sea que el procedimiento a seguir para inicializar la Toolbox */
  154.     /* es casi siempre el mismo, hemos creado una función MF_InitToolbox()*/
  155.     /* que contiene las llamadas estándar de inicialización */
  156.  
  157.     MF_InitToolbox();
  158.  
  159.     /* Ahora debemos preparar y mostrar la barra de menú, que contendrá */
  160.     /* los menús propios de nuestra aplicación */
  161.     
  162.     MF_SetupMenus();
  163.     
  164.     /* Ahora empleamos una función se encargará de abrir una ventana */
  165.     MF_AbreMiVentana();
  166.     
  167.     /* Y ya podemos entrar en el bucle principal, que se encargará de
  168.          recoger e interpretar las acciones del usuario */    
  169.     MF_bucle_principal();
  170.     
  171.     /* Cuando el bucle principal haya terminado, será porque el usuario
  172.          desea acabar el programa.
  173.          Debemos liberar la memoria ocupada por nuestra ventana. */
  174.     DisposeWindow(gMiVentana);
  175.     
  176.     /* Y ya está, al acabarse la función main(), el Sistema cerrará
  177.          nuestra aplicación de forma automática */
  178.     
  179. } /* Fin de main() y del programa */
  180.  
  181.  
  182.  
  183. /****************************************************************    */
  184. /* MF_bucle_principal                                                     */
  185. /****************************************************************    */
  186. /*
  187.     Recibe:     nada
  188.     Que hace: Entra en un bucle y espera que se produzca una acción (evento)
  189.                         Según cual sea este, reacciona llamando una de las funciones que
  190.                         hemos creado en esta demo.
  191.     Salida:      nada
  192. */
  193. void MF_bucle_principal(void)
  194. {
  195.     /* Declaramos una variable del tipo EventRecord que llamaremos el_Evento */
  196.     EventRecord    el_Evento;     
  197.                                 /* 
  198.                                 Un EventRecord es una estructura declarada
  199.                                 por Apple en el fichero UNIVERSAL HEADER
  200.                                 Events.h y formada por las siguientes
  201.                                 variables:
  202.                                                          
  203.                             struct EventRecord {
  204.                                     EventKind                what;         (qué evento)
  205.                                     UInt32                    message;    (datos del evento)
  206.                                     UInt32                    when;            (cuando se produce)
  207.                                     Point                        where;        (coordenadas del evento)
  208.                                     EventModifiers    modifiers;(estado de las teclas
  209.                                                                                             especiales: CMD, Opt, etc...) 
  210.                                     };
  211.                                 */
  212.     
  213.     WindowPtr    la_ventana;    /* Guardaremos un puntero que nos indicará en que
  214.                                                      ventana (si es el caso) se ha producido un evento */
  215.     
  216.     
  217.     short    zona_de_la_ventana; /* También guardaremos el código que indica
  218.                                                              la zona de la ventana en que se produce un evento
  219.                                                              si es del tipo mouseDown
  220.                                                         */
  221.                                                         
  222.     
  223.     Boolean    hay_evento;    /* valor de salida de la función WaitNextEvent */
  224.                                             /* Lo ignoraremos en esta demo */
  225.     
  226.     while (gAcabarProg == false)
  227.     /* Mientras la variable global gAcabarProg sea falsa, repetiremos este bucle */
  228.     /* Cuando es usuario seleccione 'Salir' del menú Archivo, cambiaremos el */
  229.     /* valor de gAcabarProg a true (cierto) */
  230.     {
  231.         
  232.         hay_evento = WaitNextEvent(everyEvent, &el_Evento, 0L, 0L);
  233.         /* WaitNextEvent es una función de la ToolBox que nos proporciona
  234.              información acerca de las posibles acciones del usuario o eventos del
  235.              Sistema. Para ello, 'llena' de información las variables de la estructura
  236.              EventRecord (el_Evento, en nuestro caso) */ 
  237.         
  238.         switch(el_Evento.what)
  239.         {
  240.             case nullEvent:
  241.                     /* Ignoramos eventos nulos (ningún evento).*/
  242.             break;
  243.                     
  244.             case keyDown:
  245.             /* Se ha pulsado una tecla. Comprobaremos si también se ha pulsado
  246.                  la tecla de CMD y si es así, llamaremos la función que responde
  247.                  a la selección de opciones de menú */
  248.                 if(el_Evento.modifiers & cmdKey) /* Tecla de CMD pulsada? */
  249.                 {
  250.                MF_MenuBar(MenuKey( el_Evento.message & charCodeMask) ) ;
  251.            }
  252.             break;
  253.                     
  254.             case autoKey:
  255.                 /* Ignoramos los eventos de repetición, generados al mantener
  256.                      pulsada una tecla */
  257.             break;
  258.                     
  259.             case mouseDown:
  260.             /* clic del ratón en algún sitio...*/
  261.                 zona_de_la_ventana = FindWindow(el_Evento.where,&la_ventana);
  262.                 switch (zona_de_la_ventana)
  263.                 {
  264.                     case inDrag:/* clic en la barra de título. Para que el usuario     */
  265.                                             /* pueda arrastrar la ventana, simplemente hemos de    */
  266.                                             /* usar la función DragWindow() que se encarga del    */
  267.                                             /* proceso, hasta que se suelte el botón del ratón     */
  268.                         DragWindow(la_ventana,el_Evento.where,&qd.screenBits.bounds);
  269.                     break;
  270.                             
  271.                     case inMenuBar: /* clic en la barra de menús */
  272.                         MF_MenuBar(MenuSelect(el_Evento.where));
  273.                     break;
  274.                             
  275.                     default:
  276.                         /* Ignoramos clics en otras zonas de la ventana */
  277.                     break;
  278.                 }
  279.             break;
  280.                     
  281.             case mouseUp:
  282.             /* ignoraremos los eventos producidos al soltar el botón del ratón */
  283.             break;
  284.                 
  285.             case diskEvt:
  286.             /* También ignoraremos los eventos producidos al insertar un disco */
  287.             break;
  288.                 
  289.             case updateEvt:
  290.                 /*
  291.                 Una ventana debe ser refrescada. Llamamos la función
  292.                 MF_Update, pasándole un puntero a la ventana en cuestión.
  293.                 La variable message de la estructura EventRecord, contiene
  294.                 dicho puntero, pero es necesario forzar (cast) su tipo al
  295.                 de WindowPtr
  296.                 */
  297.                 la_ventana = (WindowPtr)el_Evento.message;
  298.                 MF_Update( la_ventana );
  299.             break;
  300.                 
  301.             default:
  302.             /* En cualquier otro caso, ignoramos el evento */
  303.             break;
  304.                 
  305.         } /* Fin de switch(el_Evento.what) */
  306.             
  307.     } /* Fin de while (gAcabarProg == false) */
  308.         
  309.         
  310. } /* Fin de la función MF_bucle_principal() */
  311.  
  312.  
  313.  
  314. /****************************************************************    */
  315. /* MF_Update                                                                       */
  316. /****************************************************************    */
  317. /*
  318.     Esta función se emplea cuando MF_bucle_principal ha detectado un evento
  319.     del tipo updateEvt. El sistema lo genera cuando una ventana activa
  320.     es desplazada o cuando una ventana que no era la activa es activada.
  321.     En estos casos, la zona de la ventana que permanecía
  322.     oculta por otras ventanas debe ser refrescada, re-dibujando su contenido.
  323.     El sistema controla todas las ventanas abiertas y genera un evento updateEvt
  324.     cuando alguna zona de una ventana necesita ser refrescada.
  325.     
  326.     Recibe:     un puntero a la ventana que debe ser refrescada.
  327.     Que hace: Esta demo no redibuja los contenidos de la ventana, simplemente
  328.                         muestra el procedimiento a seguir.
  329.     Salida:      void (nada)
  330. */
  331. void MF_Update( WindowPtr ventana_a_refrescar)
  332. {
  333.  
  334.     GrafPtr  old_port;                            /* Declaración de una variable de tipo
  335.                                                                          puntero (pointer) a un área gráfica */
  336.     
  337.     GetPort( &old_port );                        /* Preservamos el área gráfica actual */
  338.     
  339.     SetPort( ventana_a_refrescar );    /* Cambiamos de área, seleccionando la
  340.                                                                         correspondiente a la ventana que debe
  341.                                                                         refrescarse */
  342.   
  343.   BeginUpdate( ventana_a_refrescar );
  344.    
  345.     /* Aqui deberíamos llamar las funciones adecuadas para re-dibujar los
  346.          contenidos de nuestra ventana. */
  347.       
  348.     EndUpdate( ventana_a_refrescar );
  349.  
  350.     SetPort( old_port );                    /* recuperamos el área gráfica inicial */
  351.     
  352. } /* Fin de MF_Update() */
  353.  
  354.  
  355.  
  356. /****************************************************************    */
  357. /* MF_MenuBar                                                                       */
  358. /****************************************************************    */
  359. /*
  360.     Esta función reacciona cuando MF_bucle_principal ha detectado que el clic
  361.     del ratón se ha producido en la barra de menús de nuestro programa.
  362.     
  363.     Requiere:    Recursoo ALRT en CdeCerca_5.µ.rsrc
  364.                         Concretamente el recurso ALRT nº 128 (kAlertRsrcID = 128)
  365.     Recibe:     una variable con la información del menu e item seleccionados
  366.     Que hace: Actúa en función de la posible selección de un item de alguno
  367.                         de nuestros menús.
  368.     Salida:      void (nada)
  369. */
  370. void MF_MenuBar(long algoSeleccionado)
  371. {
  372.     short    Que_Menu;
  373.     short    Que_Opcion;
  374.     short dummy;
  375.     Str255 ItemName;
  376.     GrafPtr oldPort;
  377.     
  378.     if(algoSeleccionado != 0L)
  379.     {
  380.         /* algoSeleccionado es un valor de tipo long (4 bytes)
  381.              que contiene en los 2 bytes superiores el número de menú seleccionado
  382.              y en los dos bytes inferiores, el número de la opción seleccionada
  383.              de dicho menú.
  384.              Para extraer ambos valores, emplearemos una funciones de la Toolbox,
  385.              HiWord y LoWord que nos devolverán los valores que nos interesan */
  386.              
  387.         Que_Menu = HiWord(algoSeleccionado);     /* 2 bytes superiores */
  388.         Que_Opcion = LoWord(algoSeleccionado);/* 2 bytes inferiores */
  389.         
  390.         switch(Que_Menu)
  391.         {
  392.             case kAppleMenuID:                                     /* Menú Apple                                     */
  393.                 if(Que_Opcion == kAcercaDe_Item)     /* Si es la opción 'Acerca de'     */
  394.                 {
  395.                     Alert(kAlertRsrcID,nil);
  396.                 }
  397.                 else    /* NO es 'Acerca de'. Ha de ser un item del menú Apple */
  398.                 {
  399.                     /* Obtenemos el nombre del item seleccionado */
  400.                     GetItem(gAppleMenu,Que_Opcion, ItemName);
  401.                     
  402.                     GetPort(&oldPort);
  403.                     
  404.                     /* Y lo abrimos empleando la función OpenDeskacc() */
  405.                     dummy = OpenDeskAcc(ItemName);
  406.                     
  407.                     SetPort(oldPort);
  408.                 }    
  409.             break;
  410.             
  411.             case kArchivoMenuID:                                /* Menú Archivo                                 */
  412.                 switch(Que_Opcion)
  413.                 {
  414.                     case kDemoTexto:                                /* Opción 'Demo'                                */
  415.                         MF_EscribeTexto();                        /* Escribimos el texto                     */
  416.                     break;
  417.                     
  418.                     case kSalirItem:                                /* Opción 'Salir                                 */
  419.                         gAcabarProg = true;                        /*IMPORTANTE: Cambiamos el valor de
  420.                                                                                         la variable global que nos indica
  421.                                                                                         que debemos finalizar el programa */
  422.                     break;                                                
  423.                         
  424.                 } /* Fin de switch(Que_Opcion) */
  425.                 
  426.             break;
  427.         } /* Fin de switch(Que_Menu) */
  428.         
  429.         HiliteMenu(0);
  430.         
  431.     } /* Fin de if(algoSeleccionado != 0L) */
  432.     
  433. } /* Fin de función MF_MenuBar() */
  434.  
  435.  
  436.  
  437. /****************************************************************/
  438. /* MF_EscribeTexto                                                                                         */ 
  439. /****************************************************************/
  440. /*
  441.     Dibuja en nuestra ventana el texto contenido en la variable miTexto.
  442.     No permite otras acciones mientras está ejecutándose
  443.         
  444.     Recibe:     nada
  445.     Cambia:      Dibuja en la ventana el texto de miTexto, letra a letra.
  446.     Salida:   nada
  447. */
  448. void MF_EscribeTexto(void)
  449. {
  450.     /* VARIABLES EMPLEADAS EN ESTA FUNCION */
  451.     short    LongitudDelTexto;         /* Para guardar la longitud de miTexto         */
  452.     short    indice;                                /* Un simple contador para un bucle for() */
  453.     short    AlturaDeLinea     = 70;    /* En pixels */
  454.     short    AnchoDeLetra         = 20;    /* En pixels */
  455.     short    MargenIzquierdo = 30;    /* En pixels */
  456.     short    MargenSuperior    = 20;    /* En pixels */
  457.     Point    PosicionLapiz;                /* Para obtener la posición del lápiz         */
  458.     long    TicksFinales;                    /* Necesario para la función Delay()             */
  459.     short    numero_de_fuente;         /* Más adelante, obtendremos del Sistema     */
  460.                                                             /* el número del tipo Courier y lo                 */
  461.                                                             /* guardaremos en esta variable                     */
  462.     
  463.     /* Este es el texto que queremos mostrar en la ventana */
  464.     unsigned char    *miTexto = "\pMacFormat, C de Cerca.";
  465.     
  466.     /* Este es un texto informativo que aparecerá en la parte superior
  467.          de la ventana */
  468.     unsigned char *info = "\pPulse repetidamente el botón del ratón...";
  469.     
  470.     /* miTexto es una cadena estándar 'C' de caracteres (una matriz) cuya
  471.     longitud (cuántos caracteres la forman) está indicada por el primer
  472.     elemento de la misma (Elemento 0) */
  473.     
  474.     LongitudDelTexto = miTexto[0];     /* Obtenemos la longitud del texto     */
  475.                                                                     /* y la guardamos en la variable        */
  476.                                                                     /* LongitudDelTexto */
  477.     
  478.     SetPort(gMiVentana);    /*    Siempre, antes de dibujar algo, debemos indicar
  479.                                                     al Sistema en que área gráfica (port) debe hacerlo.
  480.                                                      Para ello basta con usar la función SetPort()
  481.                                                     pasándole como parámetro el puntero a la ventana
  482.                                                     en cuestión */
  483.     
  484.     /* Como esta función podrá ser empleada más de una vez, es mejor empezar
  485.          'borrando' el contenido del rectángulo que forma la ventana */
  486.     EraseRect(&gMiVentana->portRect);
  487.     
  488.     /* 
  489.     Queremos usar texto con el tipo de letra Courier.
  490.     Primero obtenemos del Sistema, el número interno que corresponde al
  491.     tipo Courier. Para ello empleamos la función de la Toolbox GetFNum()
  492.     que nos devuelve en el segundo parámetro el número correspondiente
  493.     al tipo de letra que deseamos.
  494.     */
  495.     GetFNum("\pCourier", &numero_de_fuente);
  496.     
  497.     TextFont(numero_de_fuente);    /* usaremos el número obtenido (Courier)     */
  498.     TextSize(12);                                /* primero en tamaño de 12 puntos, para escribir */
  499.     MoveTo(5,15);                                /* la información */
  500.     TextFace(0);                                /* en tipo normal (ni negrita ni cursiva, etc...) */
  501.     ForeColor(blackColor);            /* y ajustando el color principal a negro */
  502.     DrawString(info);                        /* DrawString() dibuja el texto de la variable info*/
  503.      
  504.  
  505.      TextFace(bold);                            /* Y ahora, para el texto a color usamos tipo */
  506.     TextSize(72);                                /* en negrita (bold) y 72 puntos de tamaño*/
  507.     /* Ajustamos la posición inicial en la que empezaremos a escribir 
  508.     los caracteres en colores */
  509.     MoveTo(MargenSuperior, MargenSuperior + AlturaDeLinea);
  510.     
  511.     
  512.     /* ahora entramos en un bucle de tipo for(;;) que irá escribiendo
  513.          cada una de las letras que forman miTexto  a medida que vayamos pulsando 
  514.          el botón del ratón */
  515.     for (indice = 1; indice <= LongitudDelTexto; indice++)
  516.     {
  517.         
  518.         while(Button() == 0)     /* Esperamos una pulsación del ratón */
  519.             ;                                        /* mientras esta no se produzca, no hacemos nada */
  520.         
  521.         /* Escogemos un color al azar... */
  522.         MF_RandomColor();
  523.         
  524.         /* Dibujamos la letra del texto indicada por el índice. */
  525.         /* Empleando la función de la ToolBox DrawChar() */
  526.         DrawChar(miTexto[indice]); /* Además DrawChar() avanza la posición del lápiz*/
  527.  
  528.         
  529.         /* Nos aseguramos de no salir del margen derecho de la ventana */
  530.         /* Para ello usaremos una función de la ToolBox llamada GetPen() */
  531.         /* a la que pasaremos una variable de tipo Point (punto) */
  532.         GetPen(&PosicionLapiz);
  533.         /* Si la posición horizontal más el tamaño de una letra */
  534.         /* es mayor que el margen derecho... */
  535.         if ( (PosicionLapiz.h + AnchoDeLetra) > gMiVentana ->portRect.right)
  536.         {                    
  537.             /* Estamos en el margen derecho, debemos mover el lápiz al margen */
  538.             /* izquierdo (MargenIzquierdo) y 'bajarlo' una línea (AlturaDeLinea) */
  539.             MoveTo((MargenIzquierdo), (PosicionLapiz.v + AlturaDeLinea));
  540.             
  541.         }
  542.         /* Un tiempo de espera entre pulsaciones. Aleatorio para dar más */
  543.         /* sensación de realismo */
  544.         Delay(20, &TicksFinales);
  545.               
  546.     }    /* Fin de for (indice = 1 ... )
  547.         /* Ya está. Hemos acabado de escribir las letras de miTexto*/
  548.     SysBeep(30); /* Sonido de alerta del sistema (Para avisar que hemos acabado) */
  549.     InitCursor();/* Recuperamos el aspecto normal del cursor (flecha) */
  550.     
  551. } /* Fin de MF_EscribeTexto() */
  552.  
  553.  
  554.  
  555. /****************************************************************/
  556. /* MF_RandomColor                                                                                             */ 
  557. /****************************************************************/
  558. /*
  559.     Ajusta el color principal (no el de fondo) a un color al azar.
  560.         
  561.     Recibe:     nada
  562.     Cambia:      Color principal del área gráfica actual (en nuestro caso,
  563.                         la ventana que hemos abierto)
  564.     Salida:      nada
  565. */
  566. void MF_RandomColor(void)
  567. {
  568.     RGBColor    miRGBColor;
  569.     
  570.     miRGBColor.red        = Random();
  571.     miRGBColor.green    = Random();
  572.     miRGBColor.blue    = Random();
  573.         
  574.     RGBForeColor(&miRGBColor);
  575.     
  576. } /* Fin de MF_RandomColor() */
  577.  
  578.  
  579.  
  580. /****************************************************************/
  581. /* MF_ValorAlAzar                                                                                             */ 
  582. /****************************************************************/
  583. /*
  584.     Devuelve un número al azar entre los valores mínimo y máximo que recibe
  585.     como parámetros.
  586.     Asume que    mínimo es menor que máximo.
  587.  
  588.     Requiere: mínimo < máximo
  589.     Recibe:     Dos valores (short) para el rango
  590.     Cambia:      nada
  591.     Salida:   Valor al azar (short) entre mínimo y máximo
  592. */
  593. short MF_ValorAlAzar(short min, short max)
  594. {
  595.     unsigned short    valor;    /* El valor a devolver será entre 0-65536 */
  596.     short                        rango;    /* la diferencia entre max y min */
  597.     long                        temp;        
  598.  
  599.     valor = Random();
  600.     rango = max - min;
  601.     temp  = ((long)rango * valor) / 65536;    /* Ahora 0 <= temp <= range */
  602.     return  (temp + min);
  603.     
  604. } /* Fin de MF_ValorAlAzar() */
  605.  
  606.  
  607.  
  608. /****************************************************************    */
  609. /* MF_InitToolbox                                                                                                 */
  610. /****************************************************************    */
  611. /*
  612.     Inicializa la Toolbox Macintosh. El orden de llamada a las diversas
  613.     rutinas es significativo! No lo cambie.
  614.     En esta versión y posteriores, también inicializa el generador
  615.     de números aleatorios, empleando GetDateTime()
  616.  
  617.     Recibe:     nada
  618.     Cambia:      nada en la aplicación
  619.     Salida:      nada
  620. */
  621. void MF_InitToolbox (void)
  622. {
  623.     InitGraf(&qd.thePort);
  624.     InitFonts();
  625.     FlushEvents(everyEvent,0);
  626.     InitWindows();
  627.     InitMenus();
  628.     TEInit();
  629.     InitDialogs(0L);
  630.     InitCursor();
  631.  
  632.     /* Vamos a necesitar números aleatorios */
  633.     /* Una solución consiste en alimentar el generador de números */
  634.     /* aleatorios con el valor de fecha y hora actuales */
  635.     GetDateTime((unsigned long *)&qd.randSeed);
  636.     
  637. } /* Fin de MF_InitToolbox() */
  638.  
  639.  
  640.  
  641. /****************************************************************    */
  642. /* MF_SetupMenus                                                                                                    */
  643. /****************************************************************    */
  644. /*
  645. Inicializa y muestra los menús del programa. En esta versión se añade
  646. un nuevo menú: Edición, con los comandos habituales Mac, Deshacer, Cortar,
  647. Copiar, Pegar y Borrar.
  648.  
  649.     Requiere: Recursos MENU en CdeCerca_5.µ.rsrc
  650.                         Concretamente los recursos MENU nº 128, 129 y 130
  651.     Recibe:     nada
  652.     Cambia:      asigna valor a las globales.
  653.     Salida:   nada
  654. */
  655. void MF_SetupMenus(void)
  656. {
  657.     
  658.     gAppleMenu = GetMenu( kAppleMenuID );
  659.     gArchivoMenu = GetMenu( kArchivoMenuID );
  660.     
  661.     /* Nuevo menú. Aunque no se emplea en esta aplicación, se incluye
  662.          a efectos ilustrativos. Además, es aconsejable que todas las aplicaciones
  663.          incluyan un menú Edición. */
  664.     gEdicionMenu = GetMenu ( kEdicionMenuID );
  665.     
  666.     
  667.     AppendResMenu( gAppleMenu, 'DRVR' );
  668.     
  669.     InsertMenu(gAppleMenu, 0);
  670.     InsertMenu(gArchivoMenu, 0);
  671.     InsertMenu(gEdicionMenu, 0);
  672.     
  673.     DrawMenuBar();
  674.     
  675. } /* Fin de MF_SetupMenus() */
  676.  
  677.  
  678.     
  679. /****************************************************************    */
  680. /* MF_AbreMiVentana                                                       */
  681. /****************************************************************    */
  682. /*
  683.     Abre la ventana (la única) de nuestro programa
  684.     
  685.     Requiere: Recurso WIND nº 128 en CdeCerca_5.µ.rsrc
  686.     Recibe:     nada
  687.     Que hace: Crea una ventana...
  688.     Salida:      void (nada)
  689. */
  690. void MF_AbreMiVentana(void)
  691. {
  692.     /* ••• IMPORTANTE: •••
  693.     Si su Mac no es en color, substituya la función 
  694.     GetNewCWindow por la función GetNewWindow en la siguiente línea de código.
  695.     Todo funcionará igual pero no será tan bonito...
  696.  
  697.     Abrir una ventana en color - asumimos que posee un Mac a color!!! */
  698.     gMiVentana = GetNewCWindow(kMiVentanaRsrcID, nil, (WindowPtr)-1L);
  699.   
  700.   if(gMiVentana == nil) 
  701.           ExitToShell();    /* Si la creación de la ventana falla, 
  702.                                               posiblemente sea debido a falta de memoria libre
  703.                                               Lo más aconsejable es salir de la aplicación */
  704.                                                     
  705. } /* fin de MF_AbreMiVentana() */